package cuongnh.project.japanesediary.vocabulary.model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_vocabulary")
public class Vocabulary extends AbstractModelObject {

	@Id
	@Column(name = "vocabulary_id")
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "vocabulary_seq")
	@SequenceGenerator(name = "vocabulary_seq", sequenceName = "vocabulary_sequence", allocationSize = 1)
	private Long vocabularyId;

	@Column(name = "vocabulary", length = 10)
	private String vocabulary;

	@Column(name = "vocabulary_furigana", length = 20)
	private String furigana;

	@Column(name = "vocabulary_hanviet", length = 10)
	private String hanviet;

	@Column(name = "meaning_vietnamese", length = 500)
	private String vnMeaning;

	@Column(name = "meaning_english", length = 500)
	private String enMeaning;

	@Column(name = "meaning_japanese", length = 500)
	private String jpMeaning;

	@Column(name = "usage_vietnamese", length = 1000)
	private String vnUsage;

	@Column(name = "usage_english", length = 1000)
	private String enUsage;

	@Column(name = "usage_japanese", length = 1000)
	private String jpUsage;

	@Column(name = "created_date")
	private Date createdDate;

	@Column(name = "modified_date")
	private Date modifiedDate;

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_related", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "vocabulary_related_id") })
	private Set<Vocabulary> relatedsVocabulary = new HashSet<Vocabulary>();

	@ManyToMany(mappedBy = "relatedsVocabulary")
	private Set<Vocabulary> vocabularyRelateds = new HashSet<Vocabulary>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_homophone", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "vocabulary_homophone_id") })
	private Set<Vocabulary> vocabularyHomophones = new HashSet<Vocabulary>();

	@ManyToMany(mappedBy = "vocabularyHomophones")
	private Set<Vocabulary> homophones = new HashSet<Vocabulary>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_synonym", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "vocabulary_synonym_id") })
	private Set<Vocabulary> vocabularySynonyms = new HashSet<Vocabulary>();

	@ManyToMany(mappedBy = "vocabularySynonyms")
	private Set<Vocabulary> synonyms = new HashSet<Vocabulary>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_antonym", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "vocabulary_antonym_id") })
	private Set<Vocabulary> vocabularyAntonyms = new HashSet<Vocabulary>();

	@ManyToMany(mappedBy = "vocabularyAntonyms")
	private Set<Vocabulary> antonyms = new HashSet<Vocabulary>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_category", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "category_id") })
	private Set<Category> vocabularyCategories = new HashSet<Category>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_sentence", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "sentence_id") })
	private Set<Sentence> vocabularyExamples = new HashSet<Sentence>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_vocabulary_grammar", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "grammar_id") })
	private Set<Grammar> grammars = new HashSet<Grammar>();

	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
	@JoinTable(name = "tbl_vocabulary_part_of_speech", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "part_of_speech_id") })
	private Set<PartOfSpeech> partOfSpeechs = new HashSet<PartOfSpeech>();

	@ManyToMany(mappedBy = "compoundWords", fetch = FetchType.LAZY)
	private Set<Kanji> kanjis = new HashSet<Kanji>();
	
	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinTable(name = "tbl_text_vocabulary", joinColumns = { @JoinColumn(name = "vocabulary_id") }, inverseJoinColumns = { @JoinColumn(name = "text_id") })
	private Set<Text> vocabularyTexts = new HashSet<Text>();

	public long getVocabularyId() {
		return vocabularyId;
	}

	public void setVocabularyId(long vocabularyId) {
		this.vocabularyId = vocabularyId;
	}

	public String getVocabulary() {
		return vocabulary;
	}

	public void setVocabulary(String vocabulary) {
		this.vocabulary = vocabulary;
	}

	public String getFurigana() {
		return furigana;
	}

	public void setFurigana(String furigana) {
		this.furigana = furigana;
	}

	public String getHanviet() {
		return hanviet;
	}

	public void setHanviet(String hanviet) {
		this.hanviet = hanviet;
	}

	public String getVnMeaning() {
		return vnMeaning;
	}

	public void setVnMeaning(String vnMeaning) {
		this.vnMeaning = vnMeaning;
	}

	public String getEnMeaning() {
		return enMeaning;
	}

	public void setEnMeaning(String enMeaning) {
		this.enMeaning = enMeaning;
	}

	public String getJpMeaning() {
		return jpMeaning;
	}

	public void setJpMeaning(String jpMeaning) {
		this.jpMeaning = jpMeaning;
	}

	public String getVnUsage() {
		return vnUsage;
	}

	public void setVnUsage(String vnUsage) {
		this.vnUsage = vnUsage;
	}

	public String getEnUsage() {
		return enUsage;
	}

	public void setEnUsage(String enUsage) {
		this.enUsage = enUsage;
	}

	public String getJpUsage() {
		return jpUsage;
	}

	public void setJpUsage(String jpUsage) {
		this.jpUsage = jpUsage;
	}

	public Set<Vocabulary> getRelatedsVocabulary() {
		return relatedsVocabulary;
	}

	public void setRelatedsVocabulary(Set<Vocabulary> relatedsVocabulary) {
		this.relatedsVocabulary = relatedsVocabulary;
	}

	public Set<Vocabulary> getVocabularyRelateds() {
		return vocabularyRelateds;
	}

	public void setVocabularyRelateds(Set<Vocabulary> vocabularyRelateds) {
		this.vocabularyRelateds = vocabularyRelateds;
	}

	public void setVocabularyHomophones(Set<Vocabulary> vocabularyHomophones) {
		this.vocabularyHomophones = vocabularyHomophones;
	}

	public Set<Vocabulary> getVocabularyHomophones() {
		return vocabularyHomophones;
	}

	public void setHomophones(Set<Vocabulary> homophones) {
		this.homophones = homophones;
	}

	public Set<Vocabulary> getHomophones() {
		return homophones;
	}

	public Set<Vocabulary> getVocabularySynonyms() {
		return vocabularySynonyms;
	}

	public void setVocabularySynonyms(Set<Vocabulary> vocabularySynonyms) {
		this.vocabularySynonyms = vocabularySynonyms;
	}

	public Set<Vocabulary> getSynonyms() {
		return synonyms;
	}

	public void setSynonyms(Set<Vocabulary> synonyms) {
		this.synonyms = synonyms;
	}

	public Set<Vocabulary> getVocabularyAntonyms() {
		return vocabularyAntonyms;
	}

	public void setVocabularyAntonyms(Set<Vocabulary> vocabularyAntonyms) {
		this.vocabularyAntonyms = vocabularyAntonyms;
	}

	public Set<Vocabulary> getAntonyms() {
		return antonyms;
	}

	public void setAntonyms(Set<Vocabulary> antonyms) {
		this.antonyms = antonyms;
	}

	public Set<Category> getVocabularyCategories() {
		return vocabularyCategories;
	}

	public void setVocabularyCategories(Set<Category> vocabularyCategories) {
		Set<Category> oldValue = this.vocabularyCategories;
		this.vocabularyCategories = vocabularyCategories;
		firePropertyChange("vocabularyCategories", oldValue,
				vocabularyCategories);
	}
	
	public Set<Sentence> getVocabularyExamples() {
		return vocabularyExamples;
	}

	public void setVocabularyExamples(Set<Sentence> vocabularyExamples) {
		Set<Sentence> oldValue = this.vocabularyExamples;
		this.vocabularyExamples = vocabularyExamples;
		firePropertyChange("vocabularyExamples", oldValue, vocabularyExamples);
	}

	public Set<Grammar> getGrammars() {
		return grammars;
	}

	public void setGrammars(Set<Grammar> grammars) {
		this.grammars = grammars;
	}

	public Set<PartOfSpeech> getPartOfSpeechs() {
		return partOfSpeechs;
	}

	public void setPartOfSpeechs(Set<PartOfSpeech> partOfSpeechs) {
		this.partOfSpeechs = partOfSpeechs;
	}

	public Set<Kanji> getKanjis() {
		return kanjis;
	}

	public void setKanjis(Set<Kanji> kanjis) {
		Set<Kanji> oldValue = this.kanjis;
		this.kanjis = kanjis;
		firePropertyChange("kanjis", oldValue, kanjis);
	}
	
	public Set<Text> getVocabularyTexts() {
		return vocabularyTexts;
	}

	public void setVocabularyTexts(Set<Text> vocabularyTexts) {
		Set<Text> oldValue = this.vocabularyTexts;
		this.vocabularyTexts = vocabularyTexts;
		firePropertyChange("vocabularyTexts", oldValue,
				vocabularyTexts);		
	}

	public Date getCreatedDate() {
		return createdDate;
	}

	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	public Date getModifiedDate() {
		return modifiedDate;
	}

	public void setModifiedDate(Date modifiedDate) {
		this.modifiedDate = modifiedDate;
	}

	public void setVocabularyId(Long vocabularyId) {
		this.vocabularyId = vocabularyId;
	}

	@Override
	public boolean equals(Object obj) {
		boolean sameSame = false;

		if (obj != null && obj instanceof Vocabulary) {
			sameSame = vocabularyId.equals(((Vocabulary) obj).vocabularyId);
		}

		return sameSame;
	}

	@Override
	public int hashCode() {
		return this.vocabularyId.intValue();
	}

}
